package net.xo68.destiny.starter.manager.sched.impl;

import lombok.extern.slf4j.Slf4j;
import net.xo68.destiny.contract.domain.RespondEntity;
import net.xo68.destiny.contract.domain.StringRespondResult;
import net.xo68.destiny.contract.domain.job.TriggerParameter;
import net.xo68.destiny.contract.domain.sched.JobSchedResult;
import net.xo68.destiny.core.discovery.NodeDiscoveryClient;
import net.xo68.destiny.core.rpc.RpcClient;
import net.xo68.destiny.core.timingwheel.process.EventProcessorContext;
import net.xo68.destiny.starter.common.context.LocaleMessage;
import net.xo68.destiny.starter.common.sched.TaskTimeoutEventHandler;
import net.xo68.destiny.starter.manager.sched.JobScheduleProvider;
import net.xo68.destiny.starter.manager.worker.route.IWorkerRouteStrategy;
import net.xo68.destiny.starter.manager.worker.route.WorkerRouteStrategyManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.List;


/**
 * 超时项任务超时事件处理实现
 * @author wuxie
 * @version 2020-12-24
 */
@Slf4j
@Component
public class TaskTimeoutEventHandlerImpl implements TaskTimeoutEventHandler {

    public static final String WORKER_API_URL="/api/receive";

    private final LocaleMessage localeMessage;
    private final NodeDiscoveryClient nodeDiscoveryClient;
    private final RpcClient rpcClient;
    private final WorkerRouteStrategyManager workerRouteStrategyManager;
    private final JobScheduleProvider jobScheduleProvider;

    public TaskTimeoutEventHandlerImpl(LocaleMessage localeMessage, NodeDiscoveryClient nodeDiscoveryClient, RpcClient rpcClient, WorkerRouteStrategyManager workerRouteStrategyManager, JobScheduleProvider jobScheduleProvider) {
        this.localeMessage = localeMessage;
        this.nodeDiscoveryClient = nodeDiscoveryClient;
        this.rpcClient = rpcClient;
        this.workerRouteStrategyManager = workerRouteStrategyManager;
        this.jobScheduleProvider = jobScheduleProvider;
    }

    @Override
    public void onEvent(EventProcessorContext<TriggerParameter> processorContext) throws Exception {
        TriggerParameter triggerParameter=processorContext.triggerParameter();
        //log.debug("event 触发参数： {}",triggerParameter);

        List<String> workers = nodeDiscoveryClient.getWorkHostsByGroupName(triggerParameter.getWorkGroup());
        if(workers==null || workers.isEmpty()){
            JobSchedResult jobSchedResult=new JobSchedResult();
            jobSchedResult.setJobInstanceId(triggerParameter.getInstanceId());
            jobSchedResult.setState(RespondEntity.FAIL);
            jobSchedResult.setMessage("没有对应的worker节点");
            jobScheduleProvider.schedule(jobSchedResult);
            return;
        }

        IWorkerRouteStrategy workerRouteStrategy=workerRouteStrategyManager.getWorkerRouteStrategy(triggerParameter.getWorkerRouteStrategy());
        if(workerRouteStrategy==null){
            JobSchedResult jobSchedResult=new JobSchedResult();
            jobSchedResult.setJobInstanceId(triggerParameter.getInstanceId());
            jobSchedResult.setState(RespondEntity.FAIL);
            jobSchedResult.setMessage("未找到worker负载均衡路由策略");
            jobScheduleProvider.schedule(jobSchedResult);
            return;
        }
        String host=workerRouteStrategy.exec(workers);
        if(StringUtils.isBlank(host)){
            JobSchedResult jobSchedResult=new JobSchedResult();
            jobSchedResult.setJobInstanceId(triggerParameter.getInstanceId());
            jobSchedResult.setState(RespondEntity.FAIL);
            jobSchedResult.setMessage("执行任务的worker的host不能为空");
            jobSchedResult.setWorkers(workers);
            jobScheduleProvider.schedule(jobSchedResult);
            return;
        }

        RpcClient.TryRequestResult<StringRespondResult> tryRequestResult=rpcClient.tryPostJsonAndReturnHost(workers,host,WORKER_API_URL, StringRespondResult.class,triggerParameter);
        StringRespondResult respondResult=tryRequestResult.getReponseResult();
        if(respondResult==null || respondResult.isFail()){
            JobSchedResult jobSchedResult=new JobSchedResult();
            jobSchedResult.setJobInstanceId(triggerParameter.getInstanceId());
            jobSchedResult.setState(RespondEntity.FAIL);
            jobSchedResult.setMessage("无法连接到执行任务的worker");
            jobSchedResult.setWorkers(workers);
            jobSchedResult.setWorker(tryRequestResult.getLastRequestHost());
            jobScheduleProvider.schedule(jobSchedResult);
            return;
        }
        JobSchedResult jobSchedResult=new JobSchedResult();
        jobSchedResult.setJobInstanceId(triggerParameter.getInstanceId());
        jobSchedResult.setState(RespondEntity.SUCCESS);
        jobSchedResult.setMessage("调度成功");
        jobSchedResult.setWorkers(workers);
        jobSchedResult.setWorker(tryRequestResult.getLastRequestHost());
        jobScheduleProvider.schedule(jobSchedResult);

    }

}
